package com.billdimmick.merkabah;


import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.Properties;
import java.util.UUID;

import org.junit.Assert;
import org.junit.Test;


public class TestBasicAWSSecurityAdapter {

	@Test
	public void testStringConstructorPass() {
		String id=UUID.randomUUID().toString();
		String pass=UUID.randomUUID().toString();
		
		AWSSecurityAdapter adapter=new BasicSQSSecurityAdapter(id, pass);
		Assert.assertEquals(id, adapter.getAWSAccessId());
		Assert.assertEquals(pass, adapter.getAWSSecretKey());
	}

	@Test
	public void testStringConstructorFailure() {
		String [] emptyCombinations={"", null};
		
		for (int i=0; i<emptyCombinations.length; i++) {
			for (int j=0; j<emptyCombinations.length; j++) {
				String id=emptyCombinations[i];
				String pass=emptyCombinations[j];
				try {
					new BasicSQSSecurityAdapter(null, null);
					Assert.fail(String.format("failed for combination id=%d, secret=%d", id, pass));
				} catch (IllegalArgumentException iae) {}				
			}

			try {
				new BasicSQSSecurityAdapter(emptyCombinations[i], UUID.randomUUID().toString());
				Assert.fail(String.format("failed for id=%d and random secret", emptyCombinations[i]));
			} catch (IllegalArgumentException iae) {}				

			try {
				new BasicSQSSecurityAdapter(UUID.randomUUID().toString(), emptyCombinations[i]);
				Assert.fail(String.format("failed for secret=%d and random id", emptyCombinations[i]));
			} catch (IllegalArgumentException iae) {}							
		}
	}
		
	@Test
	public void testPropertyConstructorPass() {
		String id=UUID.randomUUID().toString();
		String pass=UUID.randomUUID().toString();
		Properties properties=new Properties();
		properties.put("AWSAccessId", id);
		properties.put("AWSSecretKey", pass);
		
		AWSSecurityAdapter adapter=new BasicSQSSecurityAdapter(properties);
		Assert.assertEquals(id, adapter.getAWSAccessId());
		Assert.assertEquals(pass, adapter.getAWSSecretKey());
	}

	@Test
	public void testPropertyConstructorFailure() {
		Properties properties=new Properties();

		String [] emptyCombinations={""};
		
		try {
			new BasicSQSSecurityAdapter(null);
			Assert.fail(String.format("failed for combination %s", properties.toString()));
		} catch (IllegalArgumentException iae) {}				
		
		try {
			new BasicSQSSecurityAdapter(properties);
			Assert.fail(String.format("failed for combination %s", properties.toString()));
		} catch (IllegalArgumentException iae) {}				
		
		for (int i=0; i<emptyCombinations.length; i++) {
			for (int j=0; j<emptyCombinations.length; j++) {
				properties.put("AWSAccessId", emptyCombinations[i]);
				properties.put("AWSSecretKey", emptyCombinations[j]);
				try {
					new BasicSQSSecurityAdapter(properties);
					Assert.fail(String.format("failed for combination %s", properties.toString()));
				} catch (IllegalArgumentException iae) {}
				properties.clear();
			}

			try {
				properties.put("AWSAccessId", emptyCombinations[i]);
				properties.put("AWSSecretKey", UUID.randomUUID().toString());
				new BasicSQSSecurityAdapter(properties);
				Assert.fail(String.format("failed for combination %s", properties.toString()));
			} catch (IllegalArgumentException iae) {}				
			properties.clear();
			
			try {
				properties.put("AWSAccessId", UUID.randomUUID().toString());
				properties.put("AWSSecretKey", emptyCombinations[i]);
				new BasicSQSSecurityAdapter(properties);
				Assert.fail(String.format("failed for combination %s", properties.toString()));
			} catch (IllegalArgumentException iae) {}
			properties.clear();
		}
	}

	@Test
	public void testStorageCallsWithIllegalArguments() throws Exception {
		final BasicSQSSecurityAdapter adapter=new BasicSQSSecurityAdapter("principal", "credential");

		try {
			adapter.addCertificate(null, null);
			Assert.fail("Expected IllegalArgumentException.");
		} catch (IllegalArgumentException iae) {}
		
		try {
			adapter.addCertificate("default", null);
			Assert.fail("Expected IllegalArgumentException.");
		} catch (IllegalArgumentException iae) {}
		
		try {
			adapter.addPrivateKey(null, null);
			Assert.fail("Expected IllegalArgumentException.");
		} catch (IllegalArgumentException iae) {}
		
		try {
			adapter.addPrivateKey("default", null);
			Assert.fail("Expected IllegalArgumentException.");
		} catch (IllegalArgumentException iae) {}
		
		try {
			adapter.addPublicKey(null, null);
			Assert.fail("Expected IllegalArgumentException.");
		} catch (IllegalArgumentException iae) {}
		
		try {
			adapter.addPublicKey("default", null);
			Assert.fail("Expected IllegalArgumentException.");
		} catch (IllegalArgumentException iae) {}
		
		try {
			adapter.generateKeypair(null);
			Assert.fail("Expected IllegalArgumentException.");
		} catch (IllegalArgumentException iae) {}
		
		try {
			adapter.generateKeypair("default", null);
			Assert.fail("Expected IllegalArgumentException.");
		} catch (IllegalArgumentException iae) {}
		
		try {
			adapter.generateKeypair("default", "RSA", -1);
			Assert.fail("Expected IllegalArgumentException.");
		} catch (IllegalArgumentException iae) {}
		
	}
	
	@Test
	public void testKeypairStorage() throws Exception {
		final BasicSQSSecurityAdapter adapter=new BasicSQSSecurityAdapter("test", "test");
		final String algorithm="RSA";
		final String name="default";
		final KeyPair pair=KeyPairGenerator.getInstance(algorithm).generateKeyPair();
		adapter.addPrivateKey(name, pair.getPrivate());
		adapter.addPublicKey(name, pair.getPublic());
		assertEqual(pair.getPrivate(), adapter.getPrivateKey(name));
		assertEqual(pair.getPublic(), adapter.getPublicKey(name));
	}

	@Test
	public void testAlgorithmAndStrengthKeypairGeneration() throws Exception {
		final BasicSQSSecurityAdapter adapter=new BasicSQSSecurityAdapter("test", "test");
		final String algorithm="RSA";
		final String name="default";
		adapter.generateKeypair(name, algorithm, 1024);
		Assert.assertNotNull(adapter.getPrivateKey(name));
		Assert.assertNotNull(adapter.getPublicKey(name));
		Assert.assertEquals(algorithm, adapter.getPrivateKey(name).getAlgorithm());
		Assert.assertEquals(algorithm, adapter.getPublicKey(name).getAlgorithm());
	}

	@Test
	public void testAlgorithmKeypairGeneration() throws Exception {
		final BasicSQSSecurityAdapter adapter=new BasicSQSSecurityAdapter("test", "test");
		final String algorithm="RSA";
		final String name="default";
		adapter.generateKeypair(name, algorithm);
		Assert.assertNotNull(adapter.getPrivateKey(name));
		Assert.assertNotNull(adapter.getPublicKey(name));
		Assert.assertEquals(algorithm, adapter.getPrivateKey(name).getAlgorithm());
		Assert.assertEquals(algorithm, adapter.getPublicKey(name).getAlgorithm());
	}

	@Test
	public void testBasicKeypairGeneration() throws Exception {
		final BasicSQSSecurityAdapter adapter=new BasicSQSSecurityAdapter("test", "test");
		final String algorithm="RSA";
		final String name="default";
		adapter.generateKeypair(name);
		Assert.assertNotNull(adapter.getPrivateKey(name));
		Assert.assertNotNull(adapter.getPublicKey(name));
		Assert.assertEquals(algorithm, adapter.getPrivateKey(name).getAlgorithm());
		Assert.assertEquals(algorithm, adapter.getPublicKey(name).getAlgorithm());
	}


	private void assertEqual(Key control, Key test) {
		Assert.assertEquals(control.getAlgorithm(), test.getAlgorithm());
		Assert.assertEquals(control.getFormat(), test.getFormat());
		Assert.assertArrayEquals(control.getEncoded(), test.getEncoded());
	}
}
